<template>
  <div class="canvas-generator">
    <h2>Canvas生成自适应文本的正方形PNG</h2>
    
    <div class="controls">
      <div class="input-group">
        <label for="text">输入文本:</label>
        <input 
          id="text" 
          v-model="inputText" 
          placeholder="请输入文本内容"
          @input="generateCanvas"
        />
      </div>
      
      <div class="input-group">
        <label for="textColor">文本颜色:</label>
        <input 
          id="textColor" 
          type="color" 
          v-model="textColor" 
          @input="generateCanvas"
        />
      </div>
      
      <div class="input-group">
        <label for="bgColor">背景颜色:</label>
        <input 
          id="bgColor" 
          type="color" 
          v-model="bgColor" 
          @input="generateCanvas"
        />
      </div>
      
      <div class="input-group">
        <label for="fontSize">字体大小:</label>
        <input 
          id="fontSize" 
          type="range" 
          min="12" 
          max="48" 
          v-model.number="fontSize" 
          @input="generateCanvas"
        />
        <span>{{ fontSize }}px</span>
      </div>
      
      <div class="input-group">
        <label for="borderRadius">圆角大小:</label>
        <input 
          id="borderRadius" 
          type="range" 
          min="0" 
          max="50" 
          v-model.number="borderRadius" 
          @input="generateCanvas"
        />
        <span>{{ borderRadius }}px</span>
      </div>
    </div>
    
    <div class="preview">
      <h3>预览:</h3>
      <canvas ref="canvasRef" class="canvas-preview"></canvas>
      <div class="download-section" v-if="canvasDataUrl">
        <a :href="canvasDataUrl" download="generated-square.png" class="download-btn">
          下载PNG图片
        </a>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, watch } from 'vue'

// 响应式数据
const inputText = ref('Hello World')
const textColor = ref('#ffffff')
const bgColor = ref('#409eff')
const fontSize = ref(24)
const borderRadius = ref(10)

// Canvas引用和数据URL
const canvasRef = ref<HTMLCanvasElement | null>(null)
const canvasDataUrl = ref('')

// 计算长方形尺寸（基于文本长度和字体大小）
const calculateRectangleSize = (text: string, font: string): { width: number, height: number } => {
  if (!canvasRef.value) return { width: 200, height: 100 }
  
  const ctx = canvasRef.value.getContext('2d')
  if (!ctx) return { width: 200, height: 100 }
  
  ctx.font = font
  const textMetrics = ctx.measureText(text)
  const textWidth = textMetrics.width
  const textHeight = fontSize.value * 1.2 // 估算文本高度
  
  // 计算长方形尺寸
  const padding = 40
  const height = textHeight + padding * 2
  const width = height + textWidth + padding * 3 // 高度 + 文本宽度 + 左侧正方形 + 间距
  
  // 确保最小尺寸
  return {
    width: Math.max(width, 200),
    height: Math.max(height, 100)
  }
}

// 生成Canvas图像
const generateCanvas = () => {
  if (!canvasRef.value) return
  
  const ctx = canvasRef.value.getContext('2d')
  if (!ctx) return
  
  // 设置字体
  const font = `${fontSize.value}px Arial, sans-serif`
  ctx.font = font
  
  // 计算长方形尺寸
  const dimensions = calculateRectangleSize(inputText.value, font)
  const { width, height } = dimensions
  
  // 设置Canvas尺寸（包括三角形的高度）
  canvasRef.value.width = width
  canvasRef.value.height = height + 30 // 增加三角形高度
  
  // 清除画布
  ctx.clearRect(0, 0, width, height + 30)
  
  // 绘制阴影效果
  ctx.save()
  ctx.shadowColor = 'rgba(0, 0, 0, 0.3)'
  ctx.shadowBlur = 10
  ctx.shadowOffsetX = 3
  ctx.shadowOffsetY = 3
  
  // 绘制圆角矩形背景
  ctx.beginPath()
  ctx.roundRect(0, 0, width, height, borderRadius.value)
  ctx.fillStyle = bgColor.value
  ctx.fill()
  ctx.restore()
  
  // 绘制左侧红色正方形
  ctx.save()
  const squareSize = height * 0.6 // 正方形大小为高度的60%
  const squareX = (height - squareSize) / 2 // 水平居中于左侧区域
  const squareY = (height - squareSize) / 2 // 垂直居中
  
  ctx.fillStyle = '#ff0000' // 红色
  ctx.fillRect(squareX, squareY, squareSize, squareSize)
  
  // 在红色正方形中心绘制数字
  ctx.fillStyle = '#ffffff' // 白色数字
  ctx.font = `${squareSize * 0.6}px Arial, sans-serif` // 字体大小为正方形大小的60%
  ctx.textAlign = 'center'
  ctx.textBaseline = 'middle'
  ctx.fillText('1', squareX + squareSize / 2, squareY + squareSize / 2) // 在正方形中心绘制数字1
  
  ctx.restore()
  
  // 绘制文本
  ctx.fillStyle = textColor.value
  ctx.font = font
  ctx.textAlign = 'left'
  ctx.textBaseline = 'middle'
  
  // 在右侧区域绘制文本（居中）
  const textX = height + (width - height) / 2 // 右侧区域的水平中心
  const textY = height / 2 // 垂直中心
  
  // 测量文本尺寸，确保不超出边界
  const textMetrics = ctx.measureText(inputText.value)
  const textWidth = textMetrics.width
  
  // 计算右侧区域的可用宽度
  const availableWidth = width - height - 40 // 减去左右边距
  
  // 如果文本过长，则截断并添加省略号
  if (textWidth > availableWidth) {
    let truncatedText = inputText.value
    while (ctx.measureText(truncatedText + '...').width > availableWidth && truncatedText.length > 0) {
      truncatedText = truncatedText.slice(0, -1)
    }
    truncatedText += '...'
    ctx.fillText(truncatedText, textX, textY)
  } else {
    ctx.fillText(inputText.value, textX, textY)
  }
  
  // 绘制底部倒立小三角形（tooltip效果）
  ctx.beginPath()
  const triangleSize = 20
  const triangleX = width / 2 // 居中
  const triangleY = height // 长方形底部
  
  // 倒立三角形（顶点在下，底部在上）
  ctx.moveTo(triangleX, triangleY + triangleSize) // 顶点（朝下）
  ctx.lineTo(triangleX - triangleSize / 2, triangleY) // 左上角
  ctx.lineTo(triangleX + triangleSize / 2, triangleY) // 右上角
  ctx.closePath()
  ctx.fillStyle = '#ff0000' // 红色
  ctx.fill()
  
  // 生成数据URL用于下载
  canvasDataUrl.value = canvasRef.value.toDataURL('image/png')
}

// 组件挂载后生成初始Canvas
onMounted(() => {
  generateCanvas()
})

// 监听输入变化并重新生成Canvas
watch([inputText, textColor, bgColor, fontSize, borderRadius], () => {
  generateCanvas()
})
</script>

<style scoped>
.canvas-generator {
  padding: 20px;
  max-width: 800px;
  margin: 0 auto;
}

.controls {
  background: #f5f5f5;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 20px;
}

.input-group {
  margin-bottom: 15px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
}

.input-group label {
  width: 100px;
  font-weight: bold;
  margin-right: 10px;
}

.input-group input[type="text"],
.input-group input[type="color"] {
  flex: 1;
  min-width: 200px;
  padding: 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.input-group input[type="range"] {
  flex: 1;
  margin-right: 10px;
}

.input-group span {
  min-width: 50px;
  text-align: right;
}

.input-group:last-child {
  margin-bottom: 0;
}

.preview {
  text-align: center;
}

.canvas-preview {
  border: 1px dashed #ddd;
  margin: 20px 0;
  max-width: 100%;
}

.download-section {
  margin: 20px 0;
}

.download-btn {
  display: inline-block;
  padding: 12px 24px;
  background-color: #409eff;
  color: white;
  text-decoration: none;
  border-radius: 4px;
  font-weight: bold;
  transition: background-color 0.3s;
}

.download-btn:hover {
  background-color: #337ecc;
}
</style>